// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Copyright (c) 2006 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
//   Lattice Semiconductor grants permission to use this code for use
//   in synthesis for any Lattice programmable logic product.  Other
//   use of this code, including the selling or duplication of any
//   portion is strictly prohibited.
//
// Disclaimer:
//
//   This VHDL or Verilog source code is intended as a design reference
//   which illustrates how these types of functions can be implemented.
//   It is the user's responsibility to verify their design for
//   consistency and functionality through the use of formal
//   verification methods.  Lattice Semiconductor provides no warranty
//   regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//           
//                     Lattice Semiconductor Corporation
//                     5555 NE Moore Court
//                     Hillsboro, OR 97214
//                     U.S.A
//
//                     TEL: 1-800-Lattice (USA and Canada)
//                          503-268-8001 (other locations)
//
//                     web: http://www.latticesemi.com/
//                     email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
//
//  Project:           7:1 LVDS Video Interface
//  File:              serializer.v
//  Title:             serializer
//  Description:       Serializer used in Tx module
//
// --------------------------------------------------------------------
//
// Revision History :
// --------------------------------------------------------------------
// $Log: serializer.vhd,v $
// Revision 1.0  2006-09-25 19:47:15-07  jhsin
// Revision 1.1  2007-11-12  hchen
//
// --------------------------------------------------------------------
`timescale 1 ns/ 1 ps

`include "lvds_7_to_1_def.v"

module serializer 
     (
      TXCLK,
      CLK,
      DATAIN,
      RST,
      tx_wr_state,
      tx_rd_state,  
      DATAOUT
     );
   
   input        TXCLK;
   input        CLK;
   input  [6:0] DATAIN;
   input        RST;
   input  [2:0] tx_wr_state;
   input  [3:0] tx_rd_state;    
   output [3:0] DATAOUT;
   
   reg  [3:0] DATAOUT;
   
   wire [6:0]  DATAIN_rev;
   reg  [55:0] ser_buf;
   reg  [3:0]  dataout_reg;
   
   reg  [4:1] buf_sel;
   wire [3:0] dataout_d;
   
   
   assign DATAIN_rev = {DATAIN[0],DATAIN[1],DATAIN[2],DATAIN[3],DATAIN[4],DATAIN[5],DATAIN[6]};
   
   always @(posedge TXCLK or posedge RST)
   begin
      if (RST)
         ser_buf <= 0;
      else
         case (tx_wr_state)
            `TX_WA1 : ser_buf[6:0]   <= DATAIN_rev;
            `TX_WB1 : ser_buf[13:7]  <= DATAIN_rev;
            `TX_WC1 : ser_buf[20:14] <= DATAIN_rev;
            `TX_WD1 : ser_buf[27:21] <= DATAIN_rev;
            `TX_WA2 : ser_buf[34:28] <= DATAIN_rev;
            `TX_WB2 : ser_buf[41:35] <= DATAIN_rev;
            `TX_WC2 : ser_buf[48:42] <= DATAIN_rev;
            `TX_WD2 : ser_buf[55:49] <= DATAIN_rev;
         endcase
   end
   
   //always @(posedge CLK or posedge RST)
   //begin
   //   if (RST)
   //      dataout_reg <= 0;
   //   else
   //      case (tx_rd_state)
   //         `TX_RA1 : dataout_reg <= ser_buf[3:0];
   //         `TX_RB1 : dataout_reg <= ser_buf[7:4];
   //         `TX_RC1 : dataout_reg <= ser_buf[11:8];
   //         `TX_RD1 : dataout_reg <= ser_buf[15:12];
   //         `TX_RE1 : dataout_reg <= ser_buf[19:16];
   //         `TX_RF1 : dataout_reg <= ser_buf[23:20];
   //         `TX_RG1 : dataout_reg <= ser_buf[27:24];
   //         `TX_RA2 : dataout_reg <= ser_buf[31:28];
   //         `TX_RB2 : dataout_reg <= ser_buf[35:32];
   //         `TX_RC2 : dataout_reg <= ser_buf[39:36];
   //         `TX_RD2 : dataout_reg <= ser_buf[43:40];
   //         `TX_RE2 : dataout_reg <= ser_buf[47:44];
   //         `TX_RF2 : dataout_reg <= ser_buf[51:48];
   //         `TX_RG2 : dataout_reg <= ser_buf[55:52];
   //      endcase
   //end
   
   // Use MUX161s to improve Fmax
      
   always @(tx_rd_state)
   begin
      case (tx_rd_state)
         `TX_RA1 : buf_sel <= 4'b0000;
         `TX_RB1 : buf_sel <= 4'b0001;
         `TX_RC1 : buf_sel <= 4'b0010;
         `TX_RD1 : buf_sel <= 4'b0011;
         `TX_RE1 : buf_sel <= 4'b0100;
         `TX_RF1 : buf_sel <= 4'b0101;
         `TX_RG1 : buf_sel <= 4'b0110;
         `TX_RA2 : buf_sel <= 4'b0111;
         `TX_RB2 : buf_sel <= 4'b1000;
         `TX_RC2 : buf_sel <= 4'b1001;
         `TX_RD2 : buf_sel <= 4'b1010;
         `TX_RE2 : buf_sel <= 4'b1011;
         `TX_RF2 : buf_sel <= 4'b1100;
         `TX_RG2 : buf_sel <= 4'b1101;
         default : buf_sel <= 4'bx;
      endcase
   end
         
   MUX161 dout_d0
          (
           .D0  (ser_buf[ 0*4]),
           .D1  (ser_buf[ 1*4]),
           .D2  (ser_buf[ 2*4]),
           .D3  (ser_buf[ 3*4]),
           .D4  (ser_buf[ 4*4]),
           .D5  (ser_buf[ 5*4]),
           .D6  (ser_buf[ 6*4]),
           .D7  (ser_buf[ 7*4]),
           .D8  (ser_buf[ 8*4]),
           .D9  (ser_buf[ 9*4]),
           .D10 (ser_buf[10*4]),
           .D11 (ser_buf[11*4]),
           .D12 (ser_buf[12*4]),
           .D13 (ser_buf[13*4]),
           .D14 (1'b0),
           .D15 (1'b0),
           .SD1 (buf_sel[1]),
           .SD2 (buf_sel[2]),
           .SD3 (buf_sel[3]),
           .SD4 (buf_sel[4]),
           .Z   (dataout_d[0])
          );
   
   MUX161 dout_d1
          (
           .D0  (ser_buf[1+ 0*4]),
           .D1  (ser_buf[1+ 1*4]),
           .D2  (ser_buf[1+ 2*4]),
           .D3  (ser_buf[1+ 3*4]),
           .D4  (ser_buf[1+ 4*4]),
           .D5  (ser_buf[1+ 5*4]),
           .D6  (ser_buf[1+ 6*4]),
           .D7  (ser_buf[1+ 7*4]),
           .D8  (ser_buf[1+ 8*4]),
           .D9  (ser_buf[1+ 9*4]),
           .D10 (ser_buf[1+10*4]),
           .D11 (ser_buf[1+11*4]),
           .D12 (ser_buf[1+12*4]),
           .D13 (ser_buf[1+13*4]),
           .D14 (1'b0),
           .D15 (1'b0),
           .SD1 (buf_sel[1]),
           .SD2 (buf_sel[2]),
           .SD3 (buf_sel[3]),
           .SD4 (buf_sel[4]),
           .Z   (dataout_d[1])
          );
       
   MUX161 dout_d2           
          (                    
           .D0  (ser_buf[2+ 0*4]),    
           .D1  (ser_buf[2+ 1*4]),    
           .D2  (ser_buf[2+ 2*4]),    
           .D3  (ser_buf[2+ 3*4]),    
           .D4  (ser_buf[2+ 4*4]),    
           .D5  (ser_buf[2+ 5*4]),    
           .D6  (ser_buf[2+ 6*4]),    
           .D7  (ser_buf[2+ 7*4]),    
           .D8  (ser_buf[2+ 8*4]),    
           .D9  (ser_buf[2+ 9*4]),    
           .D10 (ser_buf[2+10*4]),    
           .D11 (ser_buf[2+11*4]),    
           .D12 (ser_buf[2+12*4]),    
           .D13 (ser_buf[2+13*4]),    
           .D14 (1'b0),          
           .D15 (1'b0),          
           .SD1 (buf_sel[1]),   
           .SD2 (buf_sel[2]),   
           .SD3 (buf_sel[3]),   
           .SD4 (buf_sel[4]),   
           .Z   (dataout_d[2])  
          );                         
     
   MUX161 dout_d3             
          (                    
           .D0  (ser_buf[3+ 0*4]),    
           .D1  (ser_buf[3+ 1*4]),    
           .D2  (ser_buf[3+ 2*4]),    
           .D3  (ser_buf[3+ 3*4]),    
           .D4  (ser_buf[3+ 4*4]),    
           .D5  (ser_buf[3+ 5*4]),    
           .D6  (ser_buf[3+ 6*4]),    
           .D7  (ser_buf[3+ 7*4]),    
           .D8  (ser_buf[3+ 8*4]),    
           .D9  (ser_buf[3+ 9*4]),    
           .D10 (ser_buf[3+10*4]),    
           .D11 (ser_buf[3+11*4]),    
           .D12 (ser_buf[3+12*4]),    
           .D13 (ser_buf[3+13*4]),    
           .D14 (1'b0),          
           .D15 (1'b0),          
           .SD1 (buf_sel[1]),   
           .SD2 (buf_sel[2]),   
           .SD3 (buf_sel[3]),   
           .SD4 (buf_sel[4]),   
           .Z   (dataout_d[3])  
          );                         
     
                    
   always @(posedge CLK or posedge RST)
   begin
      if (RST)
         dataout_reg <= 0;
      else
         dataout_reg <= dataout_d;
   end
         
   always @(posedge CLK or posedge RST)
   begin
      if (RST)
         DATAOUT <= 0;
      else
         DATAOUT <= dataout_reg;
   end 

endmodule
